import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.kernel_ridge import KernelRidge
import scipy.optimize as optimize
# 读取Excel文件
data = pd.read_csv('5.2.csv', usecols=[0, 1])  # 假设你想读取的两列是第一列和第二列
# 提取数据
x = data.iloc[:, 0].to_numpy()  # 第一列作为 x 数据
y = data.iloc[:, 1].to_numpy()  # 第二列作为 y 数据

# x = np.arange(0, len(y))
# numpy.random.uniform(low,high,size) 从一个均匀分布[low, high)中随机采样，注意定义域是左闭右开，size输出样本数量，返回ndarray类型
noise = np.random.uniform(0, 0.1, len(x))
# print("nosie:", noise)
# y += noise
# print("Y数值", y)
fig, ax = plt.subplots()  # 创建子图函数，fig代表整个图形，ax代表图形中的坐标轴。通过对ax进行操作，便可在fig中绘制图形
ax.plot(x, y, 'b--', label='org-data')


def target_func(x, a0, a1, a2, a3):
    # 返回一个sin公式 a0振幅,a1周期、频率，圆周运动角速度，a2相位，圆周运动起始位置即时间为0时点所在位置
    return a0 * np.sin(a1 * x + a2) + a3


# 拟合sin曲线
fs = np.fft.fftfreq(len(x), x[1] - x[0])  # 傅里叶变换fft得到一个初值，fftfreq返回傅里叶变换的采样频率,自动生成一个频率范围
Y = abs(np.fft.fft(y))  # fft计算一维傅里叶变换,abs函数主要作用就是计算数字的绝对值
# print("Y: ", Y)
freq = abs(fs[np.argmax(Y[1:]) + 1])  # np.argmax用于返回一个numpy数组中最大值的索引值
# print("frep: ", freq )
a0 = max(y) - min(y)  # max() 方法返回给定参数的最大值，参数可以为序列
print("a0:", a0)
a1 = 2 * np.pi * freq
a2 = 0
a3 = np.mean(y)  # 求均值
p0 = [a0, a1, a2, a3]

para, _ = optimize.curve_fit(target_func, x, y, p0=p0)  # 三角函数拟合 p0参数的初始猜测（长度 N），如果为None，则初始值为1
print("para", para)
y_fit = [target_func(a, *para) for a in x]  # *用于参数前面，表示传入的多个参数将按照元组的形式存储,*args 表示任何多个无名参数，它本质是一个 tuple
print("*para:", *para)
ax.plot(x, y_fit, 'g', label='simu-data')
ax.legend()
plt.show()
